using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Web;
using log4net;
using log4net.Core;

namespace Geekees.App.HRAssistant.Core.Logging
{
	/// <summary>
	/// Provides logging for the Subtext framework. This class is typically instantiated as a 
	/// <c>private static readonly</c> member of a class in order to handle logging inside of 
	/// the class. This class is a specialized wrapper for the log4net framework.
	/// </summary>
	/// <para>
	/// The class provides methods to log messages at the following levels:
	/// </para>
	/// <remarks>
	/// <list type="definition">
	///	<item>
	///	<term>DEBUG</term>
	///	<description>
	///	The <see cref="M:Geekees.App.HRAssistant.Core.Logging.Log.Debug(System.Object)"/> and 
	///	<see cref="M:Geekees.App.HRAssistant.Core.Logging.Log.DebugFormat(System.String,System.Object[])"/> methods log messages
	///	at the <c>DEBUG</c> level. That is the level with that name defined in the log4net
	///	repositories. The <see cref="P:Geekees.App.HRAssistant.Core.Logging.Log.IsDebugEnabled"/>
	///	property tests if this level is enabled for logging.
	///	</description>
	///	</item>
	///	<item>
	///	<term>INFO</term>
	///	<description>
	///	The <see cref="M:Geekees.App.HRAssistant.Core.Logging.Log.Info(System.Object)"/> and 
	///	<see cref="M:Geekees.App.HRAssistant.Core.Logging.Log.InfoFormat(System.String,System.Object[])"/> methods log messages
	///	at the <c>INFO</c> level. That is the level with that name defined in the log4net
	///	repositories. The <see cref="P:Geekees.App.HRAssistant.Core.Logging.Log.IsInfoEnabled"/>
	///	property tests if this level is enabled for logging.
	///	</description>
	///	</item>
	///	<item>
	///	<term>WARN</term>
	///	<description>
	///	The <see cref="M:Geekees.App.HRAssistant.Core.Logging.Log.Warn(System.Object)"/> and 
	///	<see cref="M:Geekees.App.HRAssistant.Core.Logging.Log.WarnFormat(System.String,System.Object[])"/> methods log messages
	///	at the <c>WARN</c> level. That is the level with that name defined in the log4net
	///	repositories. The <see cref="P:Geekees.App.HRAssistant.Core.Logging.Log.IsWarnEnabled"/>
	///	property tests if this level is enabled for logging.
	///	</description>
	///	</item>
	///	<item>
	///	<term>ERROR</term>
	///	<description>
	///	The <see cref="M:Geekees.App.HRAssistant.Core.Logging.Log.Error(System.Object)"/> and 
	///	<see cref="M:Geekees.App.HRAssistant.Core.Logging.Log.ErrorFormat(System.String,System.Object[])"/> methods log messages
	///	at the <c>ERROR</c> level. That is the level with that name defined in the log4net
	///	repositories. The <see cref="P:Geekees.App.HRAssistant.Core.Logging.Log.IsErrorEnabled"/>
	///	property tests if this level is enabled for logging.
	///	</description>
	///	</item>
	///	<item>
	///	<term>FATAL</term>
	///	<description>
	///	The <see cref="M:Geekees.App.HRAssistant.Core.Logging.Log.Fatal(System.Object)"/> and 
	///	<see cref="M:Geekees.App.HRAssistant.Core.Logging.Log.FatalFormat(System.String,System.Object[])"/> methods log messages
	///	at the <c>FATAL</c> level. That is the level with that name defined in the log4net
	///	repositories. The <see cref="P:Geekees.App.HRAssistant.Core.Logging.Log.IsFatalEnabled"/>
	///	property tests if this level is enabled for logging.
	///	</description>
	///	</item>
	///	</list>
	/// </remarks>
	/// <example>
	/// An example of using the Log class
	/// <code lang="C#">
	/// public class Geekees.App.HRAssistant.Wigdetry
	/// {
	///		<b>private static readonly Log __log = new Log();</b>
	///		...
	///		public void DoSomething()
	///		{
	///			try
	///			{
	///			}
	///			catch(Exception e)
	///			{
	///				<b>__log.Error("Something had gone terribly wrong", e);</b>
	///			}
	///		}
	/// }
	/// </code>
	/// </example>
	public class Log : ILog
	{
		private static readonly ILog __nullLog = new NullLog();
		private readonly ILog _log;

		/// <summary>
		/// Default constructor. Uses <see cref="T:System.Diagnostics.StackFrame"/> to discover the class it is being called from 
		/// and automatically establishes log name as the <see cref="P:System.Type.FullName"/> of the class type.
		/// </summary>
		[MethodImpl( MethodImplOptions.NoInlining )]
		public Log()
			: this( GetCallerType() )
		{
		}

		/// <summary>
		/// Instantiates a log using the <see cref="P:System.Type.FullName"/> of the suppled type of the class as the name.
		/// </summary>
		/// <param name="type"><see cref="T:System.Type"/> of the class to create a log for</param>
		public Log( Type type )
		{
			_log = CreateInnerLogger( type );
		}

		/// <summary>
		/// Instantiates a log which wraps the specified inner logger.
		/// </summary>
		/// <param name="innerLogger"><see cref="T:System.Type"/> of the class to create a log for</param>
		public Log( ILog innerLogger )
		{
			_log = innerLogger;
		}

		private ILog CreateInnerLogger( Type type )
		{
			ILog log = LogManager.GetLogger( type );
			return log != null ? log : __nullLog;
		}

		[MethodImpl( MethodImplOptions.NoInlining )]
		private static Type GetCallerType()
		{
			return new StackFrame( 2, false ).GetMethod().DeclaringType;
		}

		/// <summary>
		/// Checks if the log is enabled for the <c>ERROR</c> level.
		/// </summary>
		/// <value>
		/// <c>true</c> if this log is enabled for the <c>ERROR</c> events, <c>false</c> otherwise
		/// </value>
		/// <remarks>
		/// <para>
		/// This function is intended to lessen the computational cost of disabled log debug statements.
		/// </para>
		/// </remarks>
		public bool IsErrorEnabled
		{
			get
			{
				return _log.IsErrorEnabled;
			}
		}

		/// <summary>
		/// Checks if the log is enabled for the <c>FATAL</c> level.
		/// </summary>
		/// <value>
		/// <c>true</c> if this log is enabled for the <c>FATAL</c> events, <c>false</c> otherwise
		/// </value>
		/// <remarks>
		/// <para>
		/// This function is intended to lessen the computational cost of disabled log debug statements.
		/// </para>
		/// </remarks>
		public bool IsFatalEnabled
		{
			get
			{
				return _log.IsFatalEnabled;
			}
		}

		/// <summary>
		/// Checks if the log is enabled for the <c>WARN</c> level.
		/// </summary>
		/// <value>
		/// <c>true</c> if this log is enabled for the <c>WARN</c> events, <c>false</c> otherwise
		/// </value>
		/// <remarks>
		/// <para>
		/// This function is intended to lessen the computational cost of disabled log debug statements.
		/// </para>
		/// </remarks>
		public bool IsWarnEnabled
		{
			get
			{
				return _log.IsWarnEnabled;
			}
		}

		/// <summary>
		/// Checks if the log is enabled for the <c>INFO</c> level.
		/// </summary>
		/// <value>
		/// <c>true</c> if this log is enabled for the <c>INFO</c> events, <c>false</c> otherwise
		/// </value>
		/// <remarks>
		/// <para>
		/// This function is intended to lessen the computational cost of disabled log debug statements.
		/// </para>
		/// </remarks>
		public bool IsInfoEnabled
		{
			get
			{
				return _log.IsInfoEnabled;
			}
		}

		/// <summary>
		/// Checks if the log is enabled for the <c>DEBUG</c> level.
		/// </summary>
		/// <value>
		/// <c>true</c> if this log is enabled for the <c>DEBUG</c> events, <c>false</c> otherwise
		/// </value>
		/// <remarks>
		/// <para>
		/// This function is intended to lessen the computational cost of disabled log debug statements.
		/// </para>
		/// </remarks>
		public bool IsDebugEnabled
		{
			get
			{
				return _log.IsDebugEnabled;
			}
		}

		/// <summary>
		/// Logs a message with the <c>ERROR</c> level.
		/// </summary>
		/// <param name="provider">An <see cref="T:System.IFormatProvider"/> that supplies culture-specific formatting information</param>
		/// <param name="format">A <see cref="T:System.String"/> containing zero or more format items</param>
		/// <param name="args">An <see cref="T:System.Array"/> containing zero or more objects to format</param>
		/// <remarks>
		/// <para>
		/// The message is formatted using the <c>String.Format</c> method. 
		/// See <see cref="M:System.String.Format(System.String,System.Object)"/> for details of the syntax 
		/// of the format string and the behavior of the formatting.
		/// </para>
		/// <para>
		/// This method does not take an <see cref="T:System.Exception"/> object to include in the log event. 
		/// To pass an <see cref="T:System.Exception"/> use
		/// one of the <see cref="M:Geekees.App.HRAssistant.Core.Logging.Log.Error(System.Object)"/> methods instead.
		/// </para>
		/// </remarks>
		public void ErrorFormat( IFormatProvider provider, string format, params object[] args )
		{
			SetUrlContext();
			_log.ErrorFormat( provider, format, args );
		}

		/// <summary>
		/// Logs a message with the <c>ERROR</c> level.
		/// </summary>
		/// <param name="format">A <see cref="T:System.String"/> containing zero or more format items</param>
		/// <param name="args">An <see cref="T:System.Array"/> containing zero or more objects to format</param>
		/// <remarks>
		/// <para>
		/// The message is formatted using the <c>String.Format</c> method. 
		/// See <see cref="M:System.String.Format(System.String,System.Object)"/> for details of the syntax 
		/// of the format string and the behavior of the formatting.
		/// </para>
		/// <para>
		/// This method does not take an <see cref="T:System.Exception"/> object to include in the log event. 
		/// To pass an <see cref="T:System.Exception"/> use
		/// one of the <see cref="M:Geekees.App.HRAssistant.Core.Logging.Log.Error(System.Object)"/> methods instead.
		/// </para>
		/// </remarks>
		public void ErrorFormat( string format, params object[] args )
		{
			SetUrlContext();
			_log.ErrorFormat( format, args );
		}

		/// <summary>
		/// Logs a message object with the <c>INFO</c> level.
		/// </summary>
		/// <param name="message">The message object to log</param>
		/// <param name="exception">The exception to log, including its stack trace</param>
		/// <remarks>
		/// <para>
		///  This method first checks if this logger is <c>INFO</c> enabled. If so, 
		///  it converts the message object (passed as parameter) to a string 
		///  by invoking the appropriate <see cref="T:log4net.ObjectRenderer.IObjectRenderer"/>. 
		///  It then proceeds to call all the registered appenders in this logger and also 
		///  higher in the hierarchy depending on the value of the additivity flag.
		/// </para>
		/// </remarks>
		public void Info( object message, Exception exception )
		{
			SetUrlContext();
			_log.Info( message, exception );
		}

		void SetUrlContext()
		{
			if( HttpContext.Current != null )
			{
				Uri url = HttpContext.Current.Request.Url;
				if( url != null && log4net.ThreadContext.Properties != null )
				{
					log4net.ThreadContext.Properties["Url"] = url.ToString();
				}
			}
		}

		/// <summary>
		/// Logs a message object with the <c>INFO</c> level.
		/// </summary>
		/// <param name="message">The message object to log</param>
		/// <remarks>
		/// <para>
		///  This method first checks if this logger is <c>INFO</c> enabled. If so, 
		///  it converts the message object (passed as parameter) to a string 
		///  by invoking the appropriate <see cref="T:log4net.ObjectRenderer.IObjectRenderer"/>. 
		///  It then proceeds to call all the registered appenders in this logger and also 
		///  higher in the hierarchy depending on the value of the additivity flag.
		/// </para>
		/// <para>
		/// <b>WARNING</b> Note that passing an <see cref="T:System.Exception"/> to this method 
		/// will print the name of the <see cref="T:System.Exception"/> but no stack trace. 
		/// To print a stack trace use the <see cref="M:Geekees.App.HRAssistant.Core.Logging.Log.Info(System.Object,System.Exception)"/> form 
		/// instead.
		/// </para>
		/// </remarks>
		public void Info( object message )
		{
			SetUrlContext();
			_log.Info( message );
		}

		/// <summary>
		/// Logs a message object with the <c>DEBUG</c> level.
		/// </summary>
		/// <param name="message">The message object to log</param>
		/// <param name="exception">The exception to log, including its stack trace</param>
		/// <remarks>
		/// <para>
		///  This method first checks if this logger is <c>DEBUG</c> enabled. If so, 
		///  it converts the message object (passed as parameter) to a string 
		///  by invoking the appropriate <see cref="T:log4net.ObjectRenderer.IObjectRenderer"/>. 
		///  It then proceeds to call all the registered appenders in this logger and also 
		///  higher in the hierarchy depending on the value of the additivity flag.
		/// </para>
		/// <para>
		/// This method is compiled to nothing if DEBUG compilation constant is not set (production build).
		/// </para>
		/// </remarks>
		public void Debug( object message, Exception exception )
		{
			SetUrlContext();
			_log.Debug( message, exception );
		}

		/// <summary>
		/// Logs a message object with the <c>DEBUG</c> level.
		/// </summary>
		/// <param name="message">The message object to log</param>
		/// <remarks>
		/// <para>
		///  This method first checks if this logger is <c>DEBUG</c> enabled. If so, 
		///  it converts the message object (passed as parameter) to a string 
		///  by invoking the appropriate <see cref="T:log4net.ObjectRenderer.IObjectRenderer"/>. 
		///  It then proceeds to call all the registered appenders in this logger and also 
		///  higher in the hierarchy depending on the value of the additivity flag.
		/// </para>
		/// <para>
		/// <b>WARNING</b> Note that passing an <see cref="T:System.Exception"/> to this method 
		/// will print the name of the <see cref="T:System.Exception"/> but no stack trace. 
		/// To print a stack trace use the <see cref="M:Geekees.App.HRAssistant.Core.Logging.Log.Debug(System.Object,System.Exception)"/> form 
		/// instead.
		/// </para>
		/// <para>
		/// This method is compiled to nothing if DEBUG compilation constant is not set (production build).
		/// </para>
		/// </remarks>
		public void Debug( object message )
		{
			SetUrlContext();
			_log.Debug( message );
		}

		/// <summary>
		/// Logs a message object with the <c>WARN</c> level.
		/// </summary>
		/// <param name="message">The message object to log</param>
		/// <param name="exception">The exception to log, including its stack trace</param>
		/// <remarks>
		/// <para>
		///  This method first checks if this logger is <c>WARN</c> enabled. If so, 
		///  it converts the message object (passed as parameter) to a string 
		///  by invoking the appropriate <see cref="T:log4net.ObjectRenderer.IObjectRenderer"/>. 
		///  It then proceeds to call all the registered appenders in this logger and also 
		///  higher in the hierarchy depending on the value of the additivity flag.
		/// </para>
		/// </remarks>
		public void Warn( object message, Exception exception )
		{
			SetUrlContext();
			_log.Warn( message, exception );
		}

		/// <summary>
		/// Logs a message object with the <c>WARN</c> level.
		/// </summary>
		/// <param name="message">The message object to log</param>
		/// <remarks>
		/// <para>
		///  This method first checks if this logger is <c>WARN</c> enabled. If so, 
		///  it converts the message object (passed as parameter) to a string 
		///  by invoking the appropriate <see cref="T:log4net.ObjectRenderer.IObjectRenderer"/>. 
		///  It then proceeds to call all the registered appenders in this logger and also 
		///  higher in the hierarchy depending on the value of the additivity flag.
		/// </para>
		/// <para>
		/// <b>WARNING</b> Note that passing an <see cref="T:System.Exception"/> to this method 
		/// will print the name of the <see cref="T:System.Exception"/> but no stack trace. 
		/// To print a stack trace use the <see cref="M:Geekees.App.HRAssistant.Core.Logging.Log.Warn(System.Object,System.Exception)"/> form 
		/// instead.
		/// </para>
		/// </remarks>
		public void Warn( object message )
		{
			SetUrlContext();
			_log.Warn( message );
		}

		/// <summary>
		/// Logs a message with the <c>WARN</c> level.
		/// </summary>
		/// <param name="provider">An <see cref="T:System.IFormatProvider"/> that supplies culture-specific formatting information</param>
		/// <param name="format">A <see cref="T:System.String"/> containing zero or more format items</param>
		/// <param name="args">An <see cref="T:System.Array"/> containing zero or more objects to format</param>
		/// <remarks>
		/// <para>
		/// The message is formatted using the <c>String.Format</c> method. 
		/// See <see cref="M:System.String.Format(System.String,System.Object)"/> for details of the syntax 
		/// of the format string and the behavior of the formatting.
		/// </para>
		/// <para>
		/// This method does not take an <see cref="T:System.Exception"/> object to include in the log event. 
		/// To pass an <see cref="T:System.Exception"/> use
		/// one of the <see cref="M:Geekees.App.HRAssistant.Core.Logging.Log.Warn(System.Object)"/> methods instead.
		/// </para>
		/// </remarks>
		public void WarnFormat( IFormatProvider provider, string format, params object[] args )
		{
			SetUrlContext();
			_log.WarnFormat( provider, format, args );
		}

		/// <summary>
		/// Logs a message with the <c>WARN</c> level.
		/// </summary>
		/// <param name="format">A <see cref="T:System.String"/> containing zero or more format items</param>
		/// <param name="args">An <see cref="T:System.Array"/> containing zero or more objects to format</param>
		/// <remarks>
		/// <para>
		/// The message is formatted using the <c>String.Format</c> method. 
		/// See <see cref="M:System.String.Format(System.String,System.Object)"/> for details of the syntax 
		/// of the format string and the behavior of the formatting.
		/// </para>
		/// <para>
		/// This method does not take an <see cref="T:System.Exception"/> object to include in the log event. 
		/// To pass an <see cref="T:System.Exception"/> use
		/// one of the <see cref="M:Geekees.App.HRAssistant.Core.Logging.Log.Warn(System.Object)"/> methods instead.
		/// </para>
		/// </remarks>
		public void WarnFormat( string format, params object[] args )
		{
			SetUrlContext();
			_log.WarnFormat( format, args );
		}

		/// <summary>
		/// Logs a message object with the <c>FATAL</c> level.
		/// </summary>
		/// <param name="message">The message object to log</param>
		/// <param name="exception">The exception to log, including its stack trace</param>
		/// <remarks>
		/// <para>
		///  This method first checks if this logger is <c>FATAL</c> enabled. If so, 
		///  it converts the message object (passed as parameter) to a string 
		///  by invoking the appropriate <see cref="T:log4net.ObjectRenderer.IObjectRenderer"/>. 
		///  It then proceeds to call all the registered appenders in this logger and also 
		///  higher in the hierarchy depending on the value of the additivity flag.
		/// </para>
		/// </remarks>
		public void Fatal( object message, Exception exception )
		{
			SetUrlContext();
			_log.Fatal( message, exception );
		}

		/// <summary>
		/// Logs a message object with the <c>FATAL</c> level.
		/// </summary>
		/// <param name="message">The message object to log</param>
		/// <remarks>
		/// <para>
		///  This method first checks if this logger is <c>FATAL</c> enabled. If so, 
		///  it converts the message object (passed as parameter) to a string 
		///  by invoking the appropriate <see cref="T:log4net.ObjectRenderer.IObjectRenderer"/>. 
		///  It then proceeds to call all the registered appenders in this logger and also 
		///  higher in the hierarchy depending on the value of the additivity flag.
		/// </para>
		/// <para>
		/// <b>WARNING</b> Note that passing an <see cref="T:System.Exception"/> to this method 
		/// will print the name of the <see cref="T:System.Exception"/> but no stack trace. 
		/// To print a stack trace use the <see cref="M:Geekees.App.HRAssistant.Core.Logging.Log.Fatal(System.Object,System.Exception)"/> form 
		/// instead.
		/// </para>
		/// </remarks>
		public void Fatal( object message )
		{
			SetUrlContext();
			_log.Fatal( message );
		}

		/// <summary>
		/// Logs a message object with the <c>ERROR</c> level.
		/// </summary>
		/// <param name="message">The message object to log</param>
		/// <param name="exception">The exception to log, including its stack trace</param>
		/// <remarks>
		/// <para>
		///  This method first checks if this logger is <c>ERROR</c> enabled. If so, 
		///  it converts the message object (passed as parameter) to a string 
		///  by invoking the appropriate <see cref="T:log4net.ObjectRenderer.IObjectRenderer"/>. 
		///  It then proceeds to call all the registered appenders in this logger and also 
		///  higher in the hierarchy depending on the value of the additivity flag.
		/// </para>
		/// </remarks>
		public void Error( object message, Exception exception )
		{
			SetUrlContext();
			_log.Error( message, exception );
		}

		/// <summary>
		/// Logs a message object with the <c>ERROR</c> level.
		/// </summary>
		/// <param name="message">The message object to log</param>
		/// <remarks>
		/// <para>
		///  This method first checks if this logger is <c>ERROR</c> enabled. If so, 
		///  it converts the message object (passed as parameter) to a string 
		///  by invoking the appropriate <see cref="T:log4net.ObjectRenderer.IObjectRenderer"/>. 
		///  It then proceeds to call all the registered appenders in this logger and also 
		///  higher in the hierarchy depending on the value of the additivity flag.
		/// </para>
		/// <para>
		/// <b>WARNING</b> Note that passing an <see cref="T:System.Exception"/> to this method 
		/// will print the name of the <see cref="T:System.Exception"/> but no stack trace. 
		/// To print a stack trace use the <see cref="M:Geekees.App.HRAssistant.Core.Logging.Log.Error(System.Object,System.Exception)"/> form 
		/// instead.
		/// </para>
		/// </remarks>
		public void Error( object message )
		{
			SetUrlContext();
			_log.Error( message );
		}

		/// <summary>
		/// Logs a message with the <c>INFO</c> level.
		/// </summary>
		/// <param name="provider">An <see cref="T:System.IFormatProvider"/> that supplies culture-specific formatting information</param>
		/// <param name="format">A <see cref="T:System.String"/> containing zero or more format items</param>
		/// <param name="args">An <see cref="T:System.Array"/> containing zero or more objects to format</param>
		/// <remarks>
		/// <para>
		/// The message is formatted using the <c>String.Format</c> method. 
		/// See <see cref="M:System.String.Format(System.String,System.Object)"/> for details of the syntax 
		/// of the format string and the behavior of the formatting.
		/// </para>
		/// <para>
		/// This method does not take an <see cref="T:System.Exception"/> object to include in the log event. 
		/// To pass an <see cref="T:System.Exception"/> use
		/// one of the <see cref="M:Geekees.App.HRAssistant.Core.Logging.Log.Info(System.Object)"/> methods instead.
		/// </para>
		/// </remarks>
		public void InfoFormat( IFormatProvider provider, string format, params object[] args )
		{
			SetUrlContext();
			_log.InfoFormat( provider, format, args );
		}

		/// <summary>
		/// Logs a message with the <c>INFO</c> level.
		/// </summary>
		/// <param name="format">A <see cref="T:System.String"/> containing zero or more format items</param>
		/// <param name="args">An <see cref="T:System.Array"/> containing zero or more objects to format</param>
		/// <remarks>
		/// <para>
		/// The message is formatted using the <c>String.Format</c> method. 
		/// of the format string and the behavior of the formatting.
		/// </para>
		/// <para>
		/// This method does not take an <see cref="T:System.Exception"/> object to include in the log event. 
		/// To pass an <see cref="T:System.Exception"/> use
		/// one of the <see cref="M:Geekees.App.HRAssistant.Core.Logging.Log.Info(System.Object)"/> methods instead.
		/// </para>
		/// </remarks>
		public void InfoFormat( string format, params object[] args )
		{
			SetUrlContext();
			_log.InfoFormat( format, args );
		}

		/// <summary>
		/// Logs a message with the <c>FATAL</c> level.
		/// </summary>
		/// <param name="provider">An <see cref="T:System.IFormatProvider"/> that supplies culture-specific formatting information</param>
		/// <param name="format">A <see cref="T:System.String"/> containing zero or more format items</param>
		/// <param name="args">An <see cref="T:System.Array"/> containing zero or more objects to format</param>
		/// <remarks>
		/// <para>
		/// The message is formatted using the <c>String.Format</c> method. 
		/// See <see cref="M:System.String.Format(System.String,System.Object)"/> for details of the syntax 
		/// of the format string and the behavior of the formatting.
		/// </para>
		/// <para>
		/// This method does not take an <see cref="T:System.Exception"/> object to include in the log event. 
		/// To pass an <see cref="T:System.Exception"/> use
		/// one of the <see cref="M:Geekees.App.HRAssistant.Core.Logging.Log.Fatal(System.Object)"/> methods instead.
		/// </para>
		/// </remarks>
		public void FatalFormat( IFormatProvider provider, string format, params object[] args )
		{
			SetUrlContext();
			_log.FatalFormat( provider, format, args );
		}

		/// <summary>
		/// Logs a message with the <c>FATAL</c> level.
		/// </summary>
		/// <param name="format">A <see cref="T:System.String"/> containing zero or more format items</param>
		/// <param name="args">An <see cref="T:System.Array"/> containing zero or more objects to format</param>
		/// <remarks>
		/// <para>
		/// The message is formatted using the <c>String.Format</c> method. 
		/// of the format string and the behavior of the formatting.
		/// </para>
		/// <para>
		/// This method does not take an <see cref="T:System.Exception"/> object to include in the log event. 
		/// To pass an <see cref="T:System.Exception"/> use
		/// one of the <see cref="M:Geekees.App.HRAssistant.Core.Logging.Log.Fatal(System.Object)"/> methods instead.
		/// </para>
		/// </remarks>
		public void FatalFormat( string format, params object[] args )
		{
			SetUrlContext();
			_log.FatalFormat( format, args );
		}

		/// <summary>
		/// Logs a message with the <c>DEBUG</c> level.
		/// </summary>
		/// <param name="provider">An <see cref="T:System.IFormatProvider"/> that supplies culture-specific formatting information</param>
		/// <param name="format">A <see cref="T:System.String"/> containing zero or more format items</param>
		/// <param name="args">An <see cref="T:System.Array"/> containing zero or more objects to format</param>
		/// <remarks>
		/// <para>
		/// The message is formatted using the <c>String.Format</c> method. 
		/// See <see cref="M:System.String.Format(System.String,System.Object)"/> for details of the syntax 
		/// of the format string and the behavior of the formatting.
		/// </para>
		/// <para>
		/// This method does not take an <see cref="T:System.Exception"/> object to include in the log event. 
		/// To pass an <see cref="T:System.Exception"/> use
		/// one of the <see cref="M:Geekees.App.HRAssistant.Core.Logging.Log.Debug(System.Object)"/> methods instead.
		/// </para>
		/// <para>
		/// This method is compiled to nothing if DEBUG compilation constant is not set (production build).
		/// </para>
		/// </remarks>
		public void DebugFormat( IFormatProvider provider, string format, params object[] args )
		{
			SetUrlContext();
			_log.DebugFormat( provider, format, args );
		}

		/// <summary>
		/// Logs a message with the <c>DEBUG</c> level.
		/// </summary>
		/// <param name="format">A <see cref="T:System.String"/> containing zero or more format items</param>
		/// <param name="args">An <see cref="T:System.Array"/> containing zero or more objects to format</param>
		/// <remarks>
		/// <para>
		/// The message is formatted using the <c>String.Format</c> method. 
		/// See <see cref="M:System.String.Format(System.String,System.Object)"/> for details of the syntax 
		/// of the format string and the behavior of the formatting.
		/// </para>
		/// <para>
		/// This method does not take an <see cref="T:System.Exception"/> object to include in the log event. 
		/// To pass an <see cref="T:System.Exception"/> use
		/// one of the <see cref="M:Geekees.App.HRAssistant.Core.Logging.Log.Debug(System.Object)"/> methods instead.
		/// </para>
		/// </remarks>
		public void DebugFormat( string format, params object[] args )
		{
			SetUrlContext();
			_log.DebugFormat( format, args );
		}

		public ILogger Logger
		{
			get
			{
				return _log.Logger;
			}
		}

		#region private class NulLog : ILog

		private class NullLog : ILog
		{
			#region ILog Members

			public void ErrorFormat( IFormatProvider provider, string format, params object[] args )
			{
			}

			void log4net.ILog.ErrorFormat( string format, params object[] args )
			{
			}

			public void Info( object message, Exception exception )
			{
			}

			void log4net.ILog.Info( object message )
			{
			}

			public void Debug( object message, Exception exception )
			{
			}

			void log4net.ILog.Debug( object message )
			{
			}

			public bool IsErrorEnabled
			{
				get
				{
					return false;
				}
			}

			public bool IsFatalEnabled
			{
				get
				{
					return false;
				}
			}

			public bool IsWarnEnabled
			{
				get
				{
					return false;
				}
			}

			public void Warn( object message, Exception exception )
			{
			}

			void log4net.ILog.Warn( object message )
			{
			}

			public bool IsInfoEnabled
			{
				get
				{
					return false;
				}
			}

			public bool IsDebugEnabled
			{
				get
				{
					return false;
				}
			}

			public void WarnFormat( IFormatProvider provider, string format, params object[] args )
			{
			}

			void log4net.ILog.WarnFormat( string format, params object[] args )
			{
			}

			public void Fatal( object message, Exception exception )
			{
			}

			void log4net.ILog.Fatal( object message )
			{
			}

			public void Error( object message, Exception exception )
			{
			}

			void log4net.ILog.Error( object message )
			{
			}

			public void InfoFormat( IFormatProvider provider, string format, params object[] args )
			{
			}

			void log4net.ILog.InfoFormat( string format, params object[] args )
			{
			}

			public void FatalFormat( IFormatProvider provider, string format, params object[] args )
			{
			}

			void log4net.ILog.FatalFormat( string format, params object[] args )
			{
			}

			public void DebugFormat( IFormatProvider provider, string format, params object[] args )
			{
			}

			void log4net.ILog.DebugFormat( string format, params object[] args )
			{
			}

			#endregion

			public ILogger Logger
			{
				get
				{
					return null;
				}
			}

			#region ILog Members


			public void DebugFormat( string format, object arg0, object arg1, object arg2 )
			{
			}

			public void DebugFormat( string format, object arg0, object arg1 )
			{
			}

			public void DebugFormat( string format, object arg0 )
			{
			}

			public void ErrorFormat( string format, object arg0, object arg1, object arg2 )
			{
			}

			public void ErrorFormat( string format, object arg0, object arg1 )
			{
			}

			public void ErrorFormat( string format, object arg0 )
			{
			}

			public void FatalFormat( string format, object arg0, object arg1, object arg2 )
			{
			}

			public void FatalFormat( string format, object arg0, object arg1 )
			{
			}

			public void FatalFormat( string format, object arg0 )
			{
			}

			public void InfoFormat( string format, object arg0, object arg1, object arg2 )
			{
			}

			public void InfoFormat( string format, object arg0, object arg1 )
			{
			}

			public void InfoFormat( string format, object arg0 )
			{
			}

			public void WarnFormat( string format, object arg0, object arg1, object arg2 )
			{
			}

			public void WarnFormat( string format, object arg0, object arg1 )
			{
			}

			public void WarnFormat( string format, object arg0 )
			{
			}

			#endregion
		}
		#endregion

		#region ILog Members


		public void DebugFormat( string format, object arg0, object arg1, object arg2 )
		{
			SetUrlContext();
			_log.DebugFormat( format, arg0, arg1, arg2 );
		}

		public void DebugFormat( string format, object arg0, object arg1 )
		{
			SetUrlContext();
			_log.DebugFormat( format, arg0, arg1 );
		}

		public void DebugFormat( string format, object arg0 )
		{
			SetUrlContext();
			_log.DebugFormat( format, arg0 );
		}

		public void ErrorFormat( string format, object arg0, object arg1, object arg2 )
		{
			SetUrlContext();
			_log.ErrorFormat( format, arg0, arg1, arg2 );
		}

		public void ErrorFormat( string format, object arg0, object arg1 )
		{
			SetUrlContext();
			_log.ErrorFormat( format, arg0, arg1 );
		}

		public void ErrorFormat( string format, object arg0 )
		{
			SetUrlContext();
			_log.ErrorFormat( format, arg0 );
		}

		public void FatalFormat( string format, object arg0, object arg1, object arg2 )
		{
			SetUrlContext();
			_log.FatalFormat( format, arg0, arg1, arg2 );
		}

		public void FatalFormat( string format, object arg0, object arg1 )
		{
			SetUrlContext();
			_log.FatalFormat( format, arg0, arg1 );
		}

		public void FatalFormat( string format, object arg0 )
		{
			SetUrlContext();
			_log.FatalFormat( format, arg0 );
		}

		public void InfoFormat( string format, object arg0, object arg1, object arg2 )
		{
			SetUrlContext();
			_log.InfoFormat( format, arg0, arg1, arg2 );
		}

		public void InfoFormat( string format, object arg0, object arg1 )
		{
			SetUrlContext();
			_log.InfoFormat( format, arg0, arg1 );
		}

		public void InfoFormat( string format, object arg0 )
		{
			SetUrlContext();
			_log.InfoFormat( format, arg0 );
		}

		public void WarnFormat( string format, object arg0, object arg1, object arg2 )
		{
			SetUrlContext();
			_log.WarnFormat( format, arg0, arg1, arg2 );
		}

		public void WarnFormat( string format, object arg0, object arg1 )
		{
			SetUrlContext();
			_log.WarnFormat( format, arg0, arg1 );
		}

		public void WarnFormat( string format, object arg0 )
		{
			SetUrlContext();
			_log.WarnFormat( format, arg0 );
		}

		#endregion
	}
}
